﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Threading;

namespace 端口扫描器
{
    public partial class MainForm : Form
    {
        private List<IPEndPoint> m_任务集合 = new List<IPEndPoint>();
        private int 总任务数;
        private int 已启动任务;
        private int 已完成任务;
        private DateTime 任务开始时间 = DateTime.Now;
        Action<string, string, int> fun; // = new Action<string>(this.写成功信息);
        private StringBuilder sb成功 = new StringBuilder();
        private StringBuilder sb失败 = new StringBuilder();

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {

        }

        private void btn开始_Click(object sender, EventArgs e)
        {
            this.btn开始.Enabled = false;
            this.任务开始时间 = DateTime.Now;
            this.已启动任务 = 0;
            this.已完成任务 = 0;
            this.sb失败.Clear();
            this.sb成功.Clear();
            this.m_任务集合.Clear();
            ThreadPool.SetMaxThreads(1000, 1000);
            ThreadPool.SetMinThreads(100, 100);
            try
            {
                //先计算任务集合
                this.m_任务集合.Clear();
                int ip范围1 = int.Parse(this.txtIP范围1.Text);
                int ip范围2 = int.Parse(this.txtIP范围2.Text);
                int ip范围3 = int.Parse(this.txtIP范围3.Text);
                int ip范围4 = int.Parse(this.txtIP范围4.Text);
                int port1 = int.Parse(this.txtPort1.Text);
                int port2 = int.Parse(this.txtPort2.Text);

                //txtIP模板为多行文本，分开处理
                string[] ip模板集合 = this.txtIP模板.Text.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string ip模板 in ip模板集合)
                {
                    string ip = ip模板.Replace(" ","");
                    if (ip.Contains(".") == false)
                        continue;  //没有点，不是合格的ip

                    if (ip.Contains("?") == false)          //如果没有？和*通配符，则前后范围写为一致，避免下面循环大量无效判断
                        ip范围1 = ip范围2;          
                    if (ip.Contains("*") == false)
                        ip范围3 = ip范围4;

                    for (int m = ip范围1; m <= ip范围2; m++)    //？号范围
                    {
                        for (int n = ip范围3; n <= ip范围4; n++)    //*范围
                        {
                            for (int port = port1; port <= port2; port++)   //端口范围
                            {
                                string t = ip.Replace("?", m.ToString()).Replace("*", n.ToString());

                                IPEndPoint p = new IPEndPoint(IPAddress.Parse(t), port);
                                if (this.m_任务集合.Contains(p) == false)
                                    this.m_任务集合.Add(p);
                                Application.DoEvents();
                            }
                        }
                    }
                }
                this.总任务数 = this.m_任务集合.Count;

                //开始异步执行任务
                foreach (IPEndPoint ip in this.m_任务集合)
                {
                    ThreadPool.QueueUserWorkItem(this.扫描端口, ip);
                    Application.DoEvents();
                }

                this.txt状态.Text = "进行中。。。。";
                this.timer显示任务.Enabled = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btn退出_Click(object sender, EventArgs e)
        {
            this.timer显示任务.Enabled = false;
            this.Close();
        }

        private void 扫描端口(object ob)
        {
            Interlocked.Increment(ref this.已启动任务);
            IPEndPoint ip = (IPEndPoint)ob;
            try
            {
                TcpClient tcp = new TcpClient();
                tcp.Connect(ip);
                //连接成功，关闭
                tcp.Close();

                lock (this.sb成功)
                {
                    this.sb成功.AppendLine($"{ip.Address}\t{ip.Port}");
                }
            }
            catch
            {
                //连接失败
                lock (this.sb失败)
                {
                    this.sb失败.AppendLine($"{ip.Address}\t{ip.Port}");
                }
            }
            finally
            {
                Interlocked.Increment(ref this.已完成任务);
            }
        }


        private void timer显示任务_Tick(object sender, EventArgs e)
        {
            this.txt进度.Text = $"{this.已完成任务} / {this.总任务数}";
            this.txt已启动任务.Text = this.已启动任务.ToString();
            TimeSpan sp = DateTime.Now - this.任务开始时间;
            this.txt耗时.Text = $"{sp.Minutes}分{sp.Seconds}秒";

            lock (this.sb失败)
            {
                this.txt连接失败.Text = this.sb失败.ToString();
            }
            lock (this.sb成功)
            {
                this.txt连接成功.Text = this.sb成功.ToString();
            }

            if (this.已完成任务 == this.总任务数)
            {
                this.timer显示任务.Enabled = false;
                this.btn开始.Enabled = true;
                this.txt状态.Text = "任务已完成";
                MessageBox.Show("扫描完成！", "消息", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }


        }

    }
}

